package com.rednote.service.task;

import com.rednote.entity.Comments;
import com.rednote.entity.Posts;
import com.rednote.mapper.CommentsMapper;
import com.rednote.mapper.PostsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Component
public class ReactionSyncTask {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private PostsMapper postMapper;

    @Autowired
    private CommentsMapper commentsMapper;

    private static final String POST_LIKE_KEY_PREFIX = "post:like:";
    private static final String COMMENT_LIKE_KEY_PREFIX = "comment:like:";
    private static final String DIRTY_POST_SET = "reaction:dirty_posts";
    private static final String DIRTY_COMMENT_SET = "reaction:dirty_comments";
    private static final String POST_LIKE_HISTORY_ZSET = "post:like:history";
    private static final String HOT_24H_ZSET = "hot:24h";
    private static final String HOT_7D_ZSET = "hot:7d";
    private static final Logger logger = LoggerFactory.getLogger(ReactionSyncTask.class);

    @Scheduled(cron = "0 0/1 * * * ?") // 每分钟执行一次
    public void syncReactionsToDatabase() {
        logger.info("定时任务同步db执行了 - {}");
        // 处理脏帖子ID集合
        Set<String> dirtyPostIds = redisTemplate.opsForSet().members(DIRTY_POST_SET);;
        if (dirtyPostIds != null && !dirtyPostIds.isEmpty()) {
            for (String raw : dirtyPostIds) {
                try {
                    Integer id = Integer.parseInt(raw);
                    String postLikeKey = POST_LIKE_KEY_PREFIX + id;
                    Long postLikeCount = redisTemplate.opsForSet().size(postLikeKey);
                    if (postLikeCount != null) {
                        Posts post = new Posts();
                        post.setPostId(id);
                        post.setLikeCount(postLikeCount.intValue());
                        postMapper.updateById(post);
                        redisTemplate.opsForValue().set("post:like:count:" + id, postLikeCount.toString(), 1, TimeUnit.HOURS);
                    }
                } catch (NumberFormatException e) {
                    // 忽略无效ID
                }
            }
            // 同步完成后清空脏帖子集合
            redisTemplate.delete(DIRTY_POST_SET);
        }

        // 处理脏评论ID集合
        Set<String> dirtyCommentIds = redisTemplate.opsForSet().members(DIRTY_COMMENT_SET);
        if (dirtyCommentIds != null && !dirtyCommentIds.isEmpty()) {
            for (String raw : dirtyCommentIds) {
                try {
                    Integer id = Integer.parseInt(raw);
                    String commentLikeKey = COMMENT_LIKE_KEY_PREFIX + id;
                    Long commentLikeCount = redisTemplate.opsForSet().size(commentLikeKey);
                    if (commentLikeCount != null) {
                        Comments comment = new Comments();
                        comment.setCommentId(id);
                        comment.setLikeCount(commentLikeCount.intValue());
                        commentsMapper.updateById(comment);
                        redisTemplate.opsForValue().set("comment:like:count:" + id, commentLikeCount.toString(), 1, TimeUnit.HOURS);
                    }
                } catch (NumberFormatException e) {
                    // 忽略无效ID
                }
            }
            // 同步完成后清空脏评论集合
            redisTemplate.delete(DIRTY_COMMENT_SET);
        }
    }

    // 定时任务：每日凌晨执行
    @Scheduled(cron = "0 0/1 * * * ?")
    public void buildHotPostRankings() {
        logger.info("定时任务构建热榜执行了 - {}");
        long now = System.currentTimeMillis();
        long oneDayAgo = now - 24 * 60 * 60 * 1000L;
        long sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000L;

        // 1. 清除历史行为日志中过期记录
        redisTemplate.opsForZSet().removeRangeByScore(POST_LIKE_HISTORY_ZSET, 0, sevenDaysAgo);

        // 2. 获取近24小时所有点赞行为
        Set<ZSetOperations.TypedTuple<String>> range24h = redisTemplate.opsForZSet()
                .rangeByScoreWithScores(POST_LIKE_HISTORY_ZSET, oneDayAgo, now);
        Map<String, Integer> count24h = new HashMap<>();
        for (ZSetOperations.TypedTuple<String> tuple : range24h) {
            String value = tuple.getValue(); // 格式 userId:postId
            String[] parts = value.split(":");
            if (parts.length != 2) continue;
            String postId = parts[1];
            count24h.put(postId, count24h.getOrDefault(postId, 0) + 1);
        }

        // 3. 构建 24h 热榜
        redisTemplate.delete(HOT_24H_ZSET);
        for (Map.Entry<String, Integer> entry : count24h.entrySet()) {
            redisTemplate.opsForZSet().add(HOT_24H_ZSET, entry.getKey(), entry.getValue());
        }

        // 4. 获取近7天所有点赞行为
        Set<ZSetOperations.TypedTuple<String>> range7d = redisTemplate.opsForZSet()
                .rangeByScoreWithScores(POST_LIKE_HISTORY_ZSET, sevenDaysAgo, now);
        Map<String, Integer> count7d = new HashMap<>();
        for (ZSetOperations.TypedTuple<String> tuple : range7d) {
            String value = tuple.getValue();
            String[] parts = value.split(":");
            if (parts.length != 2) continue;
            String postId = parts[1];
            count7d.put(postId, count7d.getOrDefault(postId, 0) + 1);
        }

        // 5. 构建 7d 热榜
        redisTemplate.delete(HOT_7D_ZSET);
        for (Map.Entry<String, Integer> entry : count7d.entrySet()) {
            redisTemplate.opsForZSet().add(HOT_7D_ZSET, entry.getKey(), entry.getValue());
        }
    }


}
